package com.titan.single.service.impl;

import com.titan.single.constant.RedisConstant;
import com.titan.single.service.RedisService;
import com.titan.single.service.TestService;
import com.titan.single.util.CompressUtil;
import com.titan.single.util.JsonUtils;
import com.titan.single.vo.BaseRequest;
import com.titan.single.vo.Car;
import com.titan.single.vo.UserVo;
import com.yomahub.liteflow.core.FlowExecutor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class TestServiceImpl implements TestService {

    @Autowired
    private FlowExecutor flowExecutor;

    @Autowired
    private RedisService redisService;

    @Override
    public void test() {

    }

    @Override
    public String liteFlow(String test) {
        BaseRequest baseRequest = new BaseRequest();
        baseRequest.setIsError(test);
        UserVo userVo = new UserVo();
        Car car = new Car();

        // 规则flowA
        flowExecutor.execute2Resp("flowA", baseRequest);
        log.info(baseRequest.toString());
        // 规则flowB
        // LiteflowResponse flowB =

        // flowExecutor.execute2Resp("flowB", baseRequest, userVo, car);

        // // 获取规则传入的第一个额外上下文对象
        //  user = flowB.getFirstContextBean();
        // // 获取规则传入的指定上下文对象
        //  car = flowB.getContextBean(Car.class);

        log.info(userVo.toString());
        log.info(car.toString());
        return "success";
    }

    @Override
    public void redisCrud() {
        UserVo userVo = new UserVo();
        userVo.setUserName("redis之王");

        // =============== 基本操作 ===============
        // 存储简单字符串
        redisService.set(RedisConstant.STR_DEMO, "简单字符串值");
        log.info("存储字符串成功key: {}", RedisConstant.STR_DEMO);

        // 获取字符串值
        Object value = redisService.get(RedisConstant.STR_DEMO);
        log.info("获取字符串值: {}", value);

        // 存储对象（带过期时间）
        redisService.set(RedisConstant.STR_DATA_DEMO, JsonUtils.objToString(userVo), 300); // 5分钟过期
        log.info("存储用户对象成功key: {}, 过期时间: 300秒", RedisConstant.STR_DATA_DEMO);

        // 获取存储的对象
        Object storedUser = redisService.get(RedisConstant.STR_DATA_DEMO);
        log.info("获取存储的用户对象: {}", storedUser);

        // 检查key是否存在
        Boolean exists = redisService.hasKey(RedisConstant.STR_DATA_DEMO);
        log.info("用户对象key是否存在: {}", exists);

        // 获取过期时间
        Long expireTime = redisService.getExpire(RedisConstant.STR_DATA_DEMO);
        log.info("keyl{},剩余过期时间: {} 秒", RedisConstant.STR_DATA_DEMO, expireTime);


        // 为已存在的key设置过期时间
        redisService.expire(RedisConstant.STR_DEMO, 600); // 10分钟
        log.info("为字符串 设置过期时间完成");

        // =============== Hash操作 ===============
        log.info("=== Redis Hash操作示例 ===");

        // 存储hash值
        redisService.hSet(RedisConstant.HASH_DEMO, "name", userVo.getUserName());
        redisService.hSet(RedisConstant.HASH_DEMO, "age", userVo.getAge());
        log.info("Hash存储完成key: {}", RedisConstant.HASH_DEMO);

        // 获取Hash中的值
        Object hashName = redisService.hGet(RedisConstant.HASH_DEMO, "name");
        Object hashAge = redisService.hGet(RedisConstant.HASH_DEMO, "age");
        log.info("从Hash-key:{} ,获取 name: {}, age: {}", RedisConstant.HASH_DEMO, hashName, hashAge);

        // =============== List操作 =============== 
        log.info("=== Redis List操作示例 ===");

        // 左边推入数据
        redisService.lPush(RedisConstant.LIST_DEMO, JsonUtils.objToString(new Car("蔚来", 1)));
        redisService.lPush(RedisConstant.LIST_DEMO, JsonUtils.objToString(new Car("宝马", 2)));
        redisService.lPush(RedisConstant.LIST_DEMO, JsonUtils.objToString(new Car("奔驰", 3)));

        // 右边弹出数据
        Object action = redisService.rPop(RedisConstant.LIST_DEMO);// 弹出"登录" 先进先出原则


        // 获取list对象
        Long lsize = redisService.lSize(RedisConstant.LIST_DEMO);
        log.info("list-key:{} , 数据量:{}", RedisConstant.LIST_DEMO, lsize);

        List<Object> list = redisService.lGetAll(RedisConstant.LIST_DEMO);
        log.info("list-key:{} ,数据:{} , 被弹出数据:{}", RedisConstant.LIST_DEMO, ArrayUtils.toString(list), action);

        // =============== Set操作 ===============
        log.info("=== Redis Set操作示例 ===");


        // 添加多个技能到Set
        Long addCount = redisService.sAdd(RedisConstant.SET_DEMO, JsonUtils.objToString(new Car("蔚来", 1)), JsonUtils.objToString(new Car("宝马", 2)), JsonUtils.objToString(new Car("奔驰", 3)), JsonUtils.objToString(new Car("极氪", 4)), JsonUtils.objToString(new Car("小米", 5)));
        log.info("Set-key:{} 添加数据，成功添加数量: {}", RedisConstant.SET_DEMO, addCount);

        // 再次添加相同技能（Set会自动去重）
        Long duplicateCount = redisService.sAdd(RedisConstant.SET_DEMO, JsonUtils.objToString(new Car("蔚来", 1)), JsonUtils.objToString(new Car("理想", 6)));
        log.info("Set-key:{} 添加数据（包含重复），新增数量: {}", RedisConstant.SET_DEMO, duplicateCount);


        Long ssize = redisService.sSize(RedisConstant.SET_DEMO);
        log.info("Set-key:{}, 数据量:{}", RedisConstant.SET_DEMO, ssize);

        Set smembers = redisService.sMembers(RedisConstant.SET_DEMO);
        log.info("Set-key:{} ,数据:{}", RedisConstant.SET_DEMO, ArrayUtils.toString(smembers.toArray()));

        Boolean b = redisService.sIsMember(RedisConstant.SET_DEMO, JsonUtils.objToString(new Car("宝马", 2)));
        log.info("Set-key:{}, 宝马是否存在:{}", RedisConstant.SET_DEMO, b);

        Object srandmember = redisService.sRandMember(RedisConstant.SET_DEMO);
        log.info("Set-key:{}, 随机获取一个对象:{}", RedisConstant.SET_DEMO, srandmember);
        // =============== 删除操作 ===============
        // log.info("=== Redis删除操作示例 ===");
        //
        // // 删除简单字符串key
        // Boolean deleteResult = redisUtils.delete(RedisConstant.STR_DEMO);
        // log.info("删除字符串key结果: {}", deleteResult);
        //
        // // 验证删除
        // Boolean existsAfterDelete = redisUtils.hasKey(RedisConstant.STR_DEMO);
        // log.info("删除后key是否还存在: {}", existsAfterDelete);

        log.info("Redis CRUD操作演示完成！");
    }


    @Override
    public void redisCompress() throws IOException {
        // 造假数据
        HashMap<String, List> map = new HashMap<>();
        List<Car> list = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            list.add(new Car("数据", i));
        }
        map.put("1", list);
        for (int i = 0; i < 10; i++) {
            map.put(String.valueOf(i), list);
        }


        // GIP- 压缩 进缓存
        long gipStartC = System.currentTimeMillis();
        redisService.setBytes("bytesGIP",CompressUtil.compressGIP(JsonUtils.objToByte(map)));
        long gipEndC =System.currentTimeMillis() -gipStartC;
        // GIP- 取缓存 解压
        long gipStartUC = System.currentTimeMillis();
        Object gipO = redisService.getBytes("bytesGIP");
        if (Objects.isNull(gipO)) {
            log.info("bytesGIP数据搜不到");
        }
        String strGIP = (String) CompressUtil.unCompressGIP(gipO);
        Map mapGIP = JsonUtils.stringToObj(strGIP, Map.class);
        log.info("GIP---压缩存缓存耗时:{},取缓存解压耗时:{}",gipEndC,System.currentTimeMillis()-gipStartUC);

        // // LZD- 压缩 进缓存
        long lzdStartC = System.currentTimeMillis();
        redisService.setBytes("bytesLZD",CompressUtil.compressLZO(JsonUtils.objToByte(map)));
        long lzdEndC =System.currentTimeMillis() -lzdStartC;
        // LZD- 取缓存 解压
        long lzdStartUC = System.currentTimeMillis();
        Object lzdO = redisService.getBytes("bytesLZD");
        String strLZD = (String) CompressUtil.uncompressLZO(lzdO);
        Map mapLZD = JsonUtils.stringToObj(strLZD, Map.class);
        log.info("LZD---压缩存缓存耗时:{},取缓存解压耗时:{}",lzdEndC,System.currentTimeMillis()-lzdStartUC);

        // // Snappy- 压缩 进缓存
        long snappyStartC = System.currentTimeMillis();
        redisService.setBytes("bytesSnappy",CompressUtil.compressSnappy(JsonUtils.objToByte(map)));
        long snappyEndC =System.currentTimeMillis() -lzdStartC;
        // Snappy- 取缓存 解压
        long snappyStartUC = System.currentTimeMillis();
        Object snappyO = redisService.getBytes("bytesSnappy");
        String strSnappy = (String) CompressUtil.unCompressSnappy(snappyO);
        Map mapSnappy = JsonUtils.stringToObj(strSnappy, Map.class);
        log.info("Snappy---压缩存缓存耗时:{},取缓存解压耗时:{}",snappyEndC,System.currentTimeMillis()-snappyStartUC);

        // // ZSTD- 压缩 进缓存
        long zstdStartC = System.currentTimeMillis();
        redisService.setBytes("bytesZSTD",CompressUtil.compressZSTD(JsonUtils.objToByte(map)));
        long zstdEndC =System.currentTimeMillis() -lzdStartC;
        // ZSTD- 取缓存 解压
        long zstdStartUC = System.currentTimeMillis();
        Object zstdO = redisService.getBytes("bytesZSTD");
        String strZSTD = (String) CompressUtil.uncompressZSTD(zstdO);
        Map mapZSTD = JsonUtils.stringToObj(strZSTD, Map.class);
        log.info("ZSTD---压缩存缓存耗时:{},取缓存解压耗时:{}",zstdEndC,System.currentTimeMillis()-zstdStartUC);


    }

    @Override
    public List<Car> completable() {
        List<Car> result = new ArrayList<>();
        UserVo userVo = new UserVo();
        long startL = System.currentTimeMillis();
        try {
            List<CompletableFuture<Void>> futureList = new ArrayList<>();
            // 数据聚合1
            CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() ->
                    completableTest1(result,userVo));
            futureList.add(completableFuture);

            // 数据聚合2
            CompletableFuture<Void> completableFuture2 = CompletableFuture.runAsync(() ->
                    completableTest2(result,userVo));
            futureList.add(completableFuture2);

            // 数据聚合3
            CompletableFuture<Void> completableFuture3 = CompletableFuture.runAsync(() ->
                    completableTest3(result,userVo));
            futureList.add(completableFuture3);

            CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).get(5, TimeUnit.SECONDS);
        }catch (Exception e) {
            log.error("多线程聚合数据异常:{}",e.getMessage(),e);
        }finally {
            log.info("总处理时间:{} ,\n数据:{},\n用户:{}",System.currentTimeMillis()-startL,ArrayUtils.toString(result),JsonUtils.objToString(userVo));
        }

        return result;
    }

    private void completableTest3(List<Car> result,UserVo userVo) {
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        // int i = 1/0;

        userVo.setUserName("李斌");
        result.add(new Car("蔚来",1));
    }

    private void completableTest2(List<Car> result,UserVo userVo) {
        // int i = 1/0;
        userVo.setUserName("雷军");
        result.add(new Car("小米",2));
    }

    private void completableTest1(List<Car> result,UserVo userVo) {
        userVo.setUserName("李想");
        result.add(new Car("理想",3));
    }


}